package com.kk.crowd.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.model.PutObjectResult;
import com.kk.crowd.constant.CrowdConstant;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/*
 * @Description:    众筹网工具类
 * @Author:         Jk_kang
 * @CreateDate:     2020/8/9 10:43
 * @Param:
 * @Return:
 **/
public class CrowdUtil {

    /**
     * 专门负责上传文件到OSS服务器的工具方法
     * @param endpoint			OSS参数
     * @param accessKeyId		OSS参数
     * @param accessKeySecret	OSS参数
     * @param inputStream		要上传的文件的输入流
     * @param bucketName		OSS参数
     * @param bucketDomain		OSS参数
     * @param originalName		要上传的文件的原始文件名
     * @return	包含上传结果以及上传的文件在OSS上的访问路径
     */
    public static ResultEntity<String> uploadFileToOss(
            String endpoint,
            String accessKeyId,
            String accessKeySecret,
            InputStream inputStream,
            String bucketName,
            String bucketDomain,
            String originalName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder ().build(endpoint, accessKeyId, accessKeySecret);

        // 生成上传文件的目录
        String folderName = new SimpleDateFormat ("yyyyMMdd").format(new Date ());

        // 生成上传文件在OSS服务器上保存时的文件名
        // 原始文件名：beautfulgirl.jpg
        // 生成文件名：wer234234efwer235346457dfswet346235.jpg
        // 使用UUID生成文件主体名称
        String fileMainName = UUID.randomUUID().toString().replace("-", "");

        // 从原始文件名中获取文件扩展名
        String extensionName = originalName.substring(originalName.lastIndexOf("."));

        // 使用目录、文件主体名称、文件扩展名称拼接得到对象名称
        String objectName = folderName + "/" + fileMainName + extensionName;

        try {
            // 调用OSS客户端对象的方法上传文件并获取响应结果数据
            PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);

            // 从响应结果中获取具体响应消息
            ResponseMessage responseMessage = putObjectResult.getResponse();

            // 根据响应状态码判断请求是否成功
            if(responseMessage == null) {

                // 拼接访问刚刚上传的文件的路径
                String ossFileAccessPath = bucketDomain + "/" + objectName;

                // 当前方法返回成功
                return ResultEntity.successWithoutData(ossFileAccessPath);
            } else {
                // 获取响应状态码
                int statusCode = responseMessage.getStatusCode();

                // 如果请求没有成功，获取错误消息
                String errorMessage = responseMessage.getErrorResponseAsString();

                // 当前方法返回失败
                return ResultEntity.failed("当前响应状态码="+statusCode+" 错误消息="+errorMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();

            // 当前方法返回失败
            return ResultEntity.failed(e.getMessage());
        } finally {

            if(ossClient != null) {

                // 关闭OSSClient。
                ossClient.shutdown();
            }
        }
    }


    /**
     * 发送短信的工具类（2）
     *
     * @param phone
     * @return
     */
    public static ResultEntity<String> sendMeagess(String host, String path, String appcode, String sign, String skin, String phone) {

        // String host = "https://feginesms.market.alicloudapi.com";// 【1】请求地址 支持http 和 https 及 WEBSOCKET
        // String path = "/codeNotice";// 【2】发送短信的具体地址
        // String appcode = "94a56a2a28be4bfea7981b0e427a5ef7"; // 【3】购买的 AppCode
        // String sign = "175622"; // 【4】签名编号
        //String skin = "15"; // 【4】模板编号
        String param = ""; // 【4】模板中的参数  eg: 大根|123456     | 隔开的是多个参数
        for (int i = 0; i < 6; i++) {
            int ran = (int) (Math.random ( ) * 10);
            param += ran;
        }
        System.out.println (param);
        //String phone = phone; // 手机号
        String urlSend = host + path + "?sign=" + sign + "&skin=" + skin + "&param=" + param + "&phone=" + phone; // 【5】拼接请求链接
        try {
            URL url = new URL (urlSend);
            HttpURLConnection httpURLCon = (HttpURLConnection) url.openConnection ( );
            httpURLCon.setRequestProperty ("Authorization", "APPCODE " + appcode);// 格式Authorization:APPCODE
            // (中间是英文空格)
            int httpCode = httpURLCon.getResponseCode ( );
            if (httpCode == 200) {
                String json = read (httpURLCon.getInputStream ( ));
                System.out.println ("正常请求计费(其他均不计费)");
                System.out.println ("获取返回的json:");
                System.out.print (json);
                // 操作成功，把生成的验证码返回
                return ResultEntity.successWithoutData (param);
            } else {
                Map<String, List<String>> map = httpURLCon.getHeaderFields ( );
                String error = map.get ("X-Ca-Error-Message").get (0);
                if (httpCode == 400 && error.equals ("Invalid AppCode `not exists`")) {
                    System.out.println ("AppCode错误 ");
                } else if (httpCode == 400 && error.equals ("Invalid Url")) {
                    System.out.println ("请求的 Method、Path 或者环境错误");
                } else if (httpCode == 400 && error.equals ("Invalid Param Location")) {
                    System.out.println ("参数错误");
                } else if (httpCode == 403 && error.equals ("Unauthorized")) {
                    System.out.println ("服务未被授权（或URL和Path不正确）");
                } else if (httpCode == 403 && error.equals ("Quota Exhausted")) {
                    System.out.println ("套餐包次数用完 ");
                } else {
                    System.out.println ("参数名错误 或 其他错误");
                    System.out.println (error);
                }
            }
        } catch (MalformedURLException e) {
            System.out.println ("URL格式错误");
        } catch (Exception e) {
            // 打开注释查看详细报错异常信息
            e.printStackTrace ( );
        }
        return ResultEntity.failed ("失败！");
    }

    /**
     * 短信读取返回结果（2）
     *
     * @param is
     * @return
     * @throws IOException
     */
    private static String read(InputStream is) throws IOException {
        StringBuffer sb = new StringBuffer ( );
        BufferedReader br = new BufferedReader (new InputStreamReader (is));
        String line = null;
        while ((line = br.readLine ( )) != null) {
            line = new String (line.getBytes ( ), "utf-8");
            sb.append (line);
        }
        br.close ( );
        return sb.toString ( );
    }


    /**
     * 对明文字符串进行 MD5 加密
     *
     * @param source 传入的明文
     * @return
     */
    public static String md5(String source) {

        // 1.判断source是否有效
        if (source == null || source.length ( ) == 0) {
            // 2.如果不是有效的字符串抛出异常
            throw new RuntimeException (CrowdConstant.MESSAGE_STRING_INVALIDATE);
        }
        try {
            // 3.获取MessageDigest对象
            String algorithm = "md5";
            MessageDigest messageDigest = MessageDigest.getInstance (algorithm);

            // 4.获取明文字符串对应的字节数组
            byte[] input = source.getBytes ( );

            // 5.执行加密
            byte[] output = messageDigest.digest (input);

            // 6.创建BigInteger对象
            int signum = 1;
            BigInteger bigInteger = new BigInteger (signum, output);

            // 7.按照16进制将bigInteger的值转换为字符串
            int radix = 16;
            String encoded = bigInteger.toString (radix).toUpperCase ( );

            return encoded;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace ( );
        }
        return null;
    }

    /**
     * 判断当前请求是否为Ajax请求
     *
     * @param request
     * @return true：当前请求是Ajax请求
     * false：当前请求不是Ajax请求
     */
    public static boolean judgeRequestType(HttpServletRequest request) {
        // 1.获取请求消息头
        String acceptHeader = request.getHeader ("Accept");
        String xRequestHeader = request.getHeader ("X-Requested-With");

        // 2.判断
        return (acceptHeader != null && acceptHeader.contains ("application/json"))
                ||
                (xRequestHeader != null && xRequestHeader.equals ("XMLHttpRequest"));
    }

}
